﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace BaseSet.Entity.Common.Text
{
    /// <summary>
    /// 对称加密算法类
    /// </summary>
    public class Encrypt : IDisposable
    {

        private static SymmetricAlgorithm mobjCryptoService;
        private static string Key;

        /// <summary>
        /// 对称加密类的构造函数
        /// </summary>
        static Encrypt()
        {
            mobjCryptoService = new RijndaelManaged();

            // 设置密钥 密钥是否可配置？
            Key = "ilovethiswebsiteverymuch";
        }

        /// <summary>
        /// 状态 做什么的？
        /// </summary>
        public SymmetricAlgorithm IsDisposed
        {
            get { return mobjCryptoService; }
            set { mobjCryptoService = value; }
        }

        /// <summary>
        /// 析构时不释放
        /// </summary>
        ~Encrypt()
        {
            InternalDispose(false);
        }

        /// <summary>
        /// 直到主动调用时 才释放
        /// </summary>
        public void Dispose()
        {
            InternalDispose(true);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing"></param>
        protected void InternalDispose(bool disposing)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// 获得密钥
        /// </summary>
        /// <returns></returns>
        private static byte[] getLegalKey()
        {
            string sTemp = Key;

            mobjCryptoService.GenerateKey();
            byte[] bytTemp = mobjCryptoService.Key;
            int keyLength = bytTemp.Length;

            if (sTemp.Length > keyLength)
            {
                sTemp = sTemp.Substring(0, keyLength);
            }
            else if (sTemp.Length < keyLength)
            {
                sTemp = sTemp.PadRight(keyLength, ' ');
            }

            return ASCIIEncoding.ASCII.GetBytes(sTemp);
        }

        /// <summary>
        /// 获得初始向量IV
        /// </summary>
        /// <returns></returns>
        private static byte[] getLegalIV()
        {
            // 失量
            string sTemp = "Doyoulovethiswebsite?";

            mobjCryptoService.GenerateIV();
            byte[] bytTemp = mobjCryptoService.IV;
            int IVLength = bytTemp.Length;

            if (sTemp.Length > IVLength)
            {
                sTemp = sTemp.Substring(0, IVLength);
            }
            else if (sTemp.Length < IVLength)
            {
                sTemp = sTemp.PadRight(IVLength, ' ');
            }

            return ASCIIEncoding.ASCII.GetBytes(sTemp);
        }

        /// <summary>
        /// 加密目标字符串 返回密文
        /// </summary>
        /// <param name="str">一个待加密的串</param>
        /// <returns></returns>
        public static string Encode(string str)
        {
            byte[] bytIn = UTF8Encoding.UTF8.GetBytes(str);

            MemoryStream ms = new MemoryStream();

            mobjCryptoService.Key = getLegalKey();
            mobjCryptoService.IV = getLegalIV();
            ICryptoTransform encrypto = mobjCryptoService.CreateEncryptor();
            CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Write);
            cs.Write(bytIn, 0, bytIn.Length);
            cs.FlushFinalBlock();
            ms.Close();
            byte[] bytOut = ms.ToArray();

            return Convert.ToBase64String(bytOut);
        }

        /// <summary>
        /// 解密目标字符串 返回明文
        /// </summary>
        /// <param name="str">一个加密的串</param>
        /// <returns></returns>
        public static string Decode(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }

            string result = str;

            try
            {
                byte[] bytIn = Convert.FromBase64String(str);
                MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length);
                mobjCryptoService.Key = getLegalKey();
                mobjCryptoService.IV = getLegalIV();
                ICryptoTransform encrypto = mobjCryptoService.CreateDecryptor();
                CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read);
                StreamReader sr = new StreamReader(cs);
                result = sr.ReadToEnd();
            }
            catch (Exception e)
            {
            }

            return result;
        }
    }
}